home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume15 / dmake-3.6 / part05 < prev    next >
Encoding:
Text File  |  1990-10-14  |  39.2 KB  |  1,258 lines

  1. Newsgroups: comp.sources.misc
  2. X-UNIX-From: dvadura@watdragon.waterloo.edu
  3. subject: v15i057: dmake version 3.6 (part 05/25)
  4. from: Dennis Vadura <dvadura@watdragon.waterloo.edu>
  5. Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  6.  
  7. Posting-number: Volume 15, Issue 57
  8. Submitted-by: Dennis Vadura <dvadura@watdragon.waterloo.edu>
  9. Archive-name: dmake-3.6/part05
  10.  
  11. #!/bin/sh
  12. # this is part 5 of a multipart archive
  13. # do not concatenate these parts, unpack them in order with /bin/sh
  14. # file sysintf.c continued
  15. #
  16. CurArch=5
  17. if test ! -r s2_seq_.tmp
  18. then echo "Please unpack part 1 first!"
  19.      exit 1; fi
  20. ( read Scheck
  21.   if test "$Scheck" != $CurArch
  22.   then echo "Please unpack part $Scheck next!"
  23.        exit 1;
  24.   else exit 0; fi
  25. ) < s2_seq_.tmp || exit 1
  26. echo "x - Continuing file sysintf.c"
  27. sed 's/^X//' << 'SHAR_EOF' >> sysintf.c
  28. X   }
  29. X}
  30. SHAR_EOF
  31. echo "File sysintf.c is complete"
  32. chmod 0440 sysintf.c || echo "restore of sysintf.c fails"
  33. echo "x - extracting struct.h (Text)"
  34. sed 's/^X//' << 'SHAR_EOF' > struct.h &&
  35. X/* RCS      -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/struct.h,v 1.1 90/10/06 12:04:27 dvadura Exp $
  36. X-- SYNOPSIS -- structure definitions
  37. X-- 
  38. X-- DESCRIPTION
  39. X--    dmake main data structure definitions.  See each of the individual
  40. X--    struct declarations for more detailed information on the defined
  41. X--    fields and their use.
  42. X-- 
  43. X-- AUTHOR
  44. X--      Dennis Vadura, dvadura@watdragon.uwaterloo.ca
  45. X--      CS DEPT, University of Waterloo, Waterloo, Ont., Canada
  46. X--
  47. X-- COPYRIGHT
  48. X--      Copyright (c) 1990 by Dennis Vadura.  All rights reserved.
  49. X-- 
  50. X--      This program is free software; you can redistribute it and/or
  51. X--      modify it under the terms of the GNU General Public License
  52. X--      (version 1), as published by the Free Software Foundation, and
  53. X--      found in the file 'LICENSE' included with this distribution.
  54. X-- 
  55. X--      This program is distributed in the hope that it will be useful,
  56. X--      but WITHOUT ANY WARRANTY; without even the implied warrant of
  57. X--      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  58. X--      GNU General Public License for more details.
  59. X-- 
  60. X--      You should have received a copy of the GNU General Public License
  61. X--      along with this program;  if not, write to the Free Software
  62. X--      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  63. X--
  64. X-- LOG
  65. X--     $Log:    struct.h,v $
  66. X * Revision 1.1  90/10/06  12:04:27  dvadura
  67. X * dmake Release, Version 3.6
  68. X * 
  69. X*/
  70. X
  71. X#ifndef _STRUCT_INCLUDED_
  72. X#define _STRUCT_INCLUDED_
  73. X
  74. X#include <sys/types.h>
  75. X#include "itypes.h"
  76. X
  77. Xtypedef int32 t_attr;
  78. X
  79. X/* The following struct is the cell used in the hash table.
  80. X * NOTE:  It contains the actual hash value.  This allows the hash table
  81. X *        insertion to compare hash values and to do a string compare only
  82. X *        for entries that have matching hash_key values.  This elliminates
  83. X *        99.9999% of all extraneous string compare operations when searching
  84. X *        a hash table chain for matching entries.  */
  85. X
  86. Xtypedef struct hcell {
  87. X    struct hcell    *ht_next;    /* next entry in the hash table */
  88. X    char        *ht_name;    /* name of this cell */
  89. X    char        *ht_value;    /* cell value if and */
  90. X    uint32        ht_hash;    /* actual hash_value of cell */
  91. X    int        ht_flag;    /* flags belonging to hash entry */
  92. X
  93. X    /* NOTE: some macros have corresponding variables defined
  94. X     * that control program behaviour.  For these macros a
  95. X     * bit of ht_flag indicates the variable value will be set, and the
  96. X     * type of the value that will be set.
  97. X     *
  98. X     * The struct below contains a mask for bit variables, and a
  99. X     * pointer to the global STATIC location for that variable.
  100. X     * String and char variables point to the same place as ht_value
  101. X     * and must be updated when ht_value changes, bit variables must
  102. X     * have their value recomputed. See Def_macro code for more
  103. X     * details.
  104. X     *
  105. X     * NOTE:  Macro variables and Targets are always distinct.  Thus
  106. X     * the value union contains pointers back at cells that own
  107. X     * a particular name entry.  A conflict in this can never
  108. X     * arise, ie pointers at cells will never be used as
  109. X     * values for a macro variable, since the cell and macro
  110. X     * name spaces are completely distinct. */
  111. X
  112. X    struct {
  113. X        int    mv_mask;    /* bit mask for bit variable      */
  114. X        union {
  115. X             char**    mv_svar;/* ptr to string valued glob var  */
  116. X            char*    mv_cvar;/* ptr to char   valued glob var */
  117. X            t_attr*    mv_bvar;/* ptr to bit    valued glob var */
  118. X             int*    mv_ivar;/* ptr to int    valued glob var  */
  119. X
  120. X            struct {
  121. X               struct tcell* ht_owner;/* ptr to CELL owning name */
  122. X               struct tcell* ht_root; /* rootdir ptr for hash    */
  123. X            } ht;
  124. X        } val;
  125. X    } var;                /* variable's static equivalent */
  126. X} HASH, *HASHPTR;
  127. X
  128. X#define MV_MASK        var.mv_mask
  129. X#define MV_SVAR     var.val.mv_svar
  130. X#define MV_CVAR     var.val.mv_cvar
  131. X#define MV_BVAR     var.val.mv_bvar
  132. X#define MV_IVAR     var.val.mv_ivar
  133. X#define CP_OWNR         var.val.ht.ht_owner
  134. X#define CP_ROOT        var.val.ht.ht_root
  135. X
  136. X
  137. X
  138. X/* This struct holds the list of temporary files that have been created.
  139. X * It gets unlinked when Quit is called due to an execution error */
  140. Xtypedef struct flst {
  141. X   char        *fl_name;    /* file name         */
  142. X   FILE        *fl_file;    /* the open file    */
  143. X   struct flst  *fl_next;    /* pointer to next file */
  144. X} FILELIST, *FILELISTPTR;
  145. X
  146. X
  147. X
  148. X/* This is the structure of a target cell in the dag which represents the
  149. X * graph of dependencies.  Each possible target is represented as a cell.
  150. X * 
  151. X * Each cell contains a pointer to the hash table entry for this cell.
  152. X * The hash table entry records the name of the cell. */
  153. X
  154. Xtypedef struct tcell {
  155. X    struct tcell    *ce_link;    /* link for temporary list making   */
  156. X    struct tcell    *ce_all;    /* link for grouping UPDATEALL cells*/
  157. X    struct hcell    *ce_name;    /* name of this cell                */
  158. X    struct tcell    *ce_setdir;    /* .SETDIR root for this cell       */
  159. X    union {
  160. X        struct hwcell    *ce_how;/* tell all we need to make cell    */
  161. X        struct edge    *ce_edges;/* tell what we can infer */
  162. X    } how;
  163. X    char        *ce_lib;    /* archive name, if A_LIBRARYM      */
  164. X    char        *ce_fname;    /* file name associated with target */
  165. X    char        *ce_dir;    /* dir to set if A_SETDIR set       */
  166. X    int           ce_flag;    /* all kinds of goodies            */
  167. X    t_attr        ce_attr;    /* attributes for this target        */
  168. X    time_t        ce_time;    /* time stamp value of target if any*/
  169. X} CELL, *CELLPTR;
  170. X
  171. X#define CE_NAME        ce_name->ht_name
  172. X#define CE_RECIPE       how.ce_how->hw_recipe
  173. X#define CE_PRQ        how.ce_how->hw_prq
  174. X#define CE_EDGES    how.ce_edges
  175. X#define CE_HOW        how.ce_how
  176. X
  177. X
  178. X
  179. X/* This struct represents that used by Get_token to return and control
  180. X * access to a token list inside a particular string.  This gives the
  181. X * ability to access non overlapping tokens simultaneously from
  182. X * multiple strings. */
  183. X    
  184. Xtypedef struct {
  185. X    char *tk_str;              /* the string to search for tokens  */
  186. X    char tk_cchar;             /* current char under *str          */
  187. X    int  tk_quote;               /* if we are scanning a quoted str  */
  188. X}  TKSTR, *TKSTRPTR;
  189. X
  190. X
  191. X
  192. X
  193. X/* This structure defines the necessary fields for handling the :: rules,
  194. X * any flags, and the fact that the target has been made using this
  195. X * set of rules.  All attributes active when making this target are
  196. X * defined in this struct. */
  197. X
  198. Xtypedef struct hwcell {
  199. X    struct hwcell    *hw_next;    /* next set of rules (::)    */
  200. X    struct lcell    *hw_prq;    /* the list of prerequisites    */
  201. X    struct lcell    *hw_indprq;    /* the list of glob prereqs    */
  202. X    struct str    *hw_recipe;    /* list of rules for making tg    */
  203. X    char        *hw_per;    /* value of % in % meta rules    */
  204. X    FILELISTPTR    hw_files;    /* temp files associated with tg*/
  205. X    int           hw_flag;    /* flags for using these rules  */
  206. X    t_attr        hw_attr;    /* attrs for using these rules  */
  207. X} HOW, *HOWPTR;
  208. X
  209. X#define HW_FLAG        CE_HOW->hw_flag
  210. X#define HW_ATTR        CE_HOW->hw_attr
  211. X
  212. X
  213. X
  214. X
  215. X/* Below is the struct used to represent a string.  It points at possibly
  216. X * another string, since the set of rules for making a target is a collection
  217. X * of strings. */
  218. X
  219. X
  220. Xtypedef struct str {
  221. X    char        *st_string;    /* the string value */
  222. X    struct str    *st_next;    /* pointer to the next string */
  223. X    t_attr        st_attr;    /* attr for rule operations */
  224. X} STRING, *STRINGPTR;
  225. X
  226. X
  227. X/* The next struct is used to link together prerequisite lists */
  228. X
  229. Xtypedef struct lcell {
  230. X    struct tcell    *cl_prq;    /* link to a prerequisite     */
  231. X    struct lcell    *cl_next;    /* next cell on dependency list */
  232. X    int        cl_flag;    /* flags for link cell        */
  233. X} LINK, *LINKPTR;
  234. X
  235. X
  236. X
  237. X/* This struct is used to define an edge in the graph of % rules */
  238. X
  239. Xtypedef struct edge {
  240. X    struct tcell    *ed_tg;        /* the % target            */
  241. X    struct tcell    *ed_prq;    /* the prerequisite for target    */
  242. X    struct hwcell    *ed_how;    /* chain of how pointers    */
  243. X    struct edge    *ed_next;    /* next edge of graph        */
  244. X    struct edge    *ed_link;    /* work list pointer         */
  245. X} EDGE, *EDGEPTR;
  246. X
  247. X
  248. X
  249. X
  250. X/* These structs are used in processing of the % rules, and in building
  251. X * the NFA machine that is used to match an arbitrary target string to
  252. X * one of the % rules that is represented by each DFA */
  253. X
  254. Xtypedef int16 statecnt;        /* limits the max number of dfa states    */
  255. X
  256. X
  257. X/* Each state of the DFA contains four pieces of information. */
  258. Xtypedef struct st {
  259. X    struct st    *no_match;    /* state to go to if no match */
  260. X    struct st    *match;        /* state to go to if we do match */
  261. X    char        symbol;        /* symbol on which we transit */
  262. X    char        action;        /* action to perform if match */
  263. X} STATE, *STATEPTR;
  264. X
  265. X
  266. X/* Each DFA machine looks like this.  It must have two pointers that represent
  267. X * the value of % in the matched string, and it contains a pointer into the
  268. X * current state, as well as the array of all states. */
  269. Xtypedef struct {
  270. X    char        *pstart;    /* start of % string match */
  271. X    char        *pend;        /* end of % string match */
  272. X    STATEPTR    c_state;    /* current DFA state */
  273. X    CELLPTR        node;        /* % target represented by this DFA */
  274. X    STATEPTR    states;        /* table of states for the DFA */
  275. X} DFA, *DFAPTR;
  276. X
  277. X
  278. X/* An NFA is a collection of DFA's.  For each DFA we must know it's current
  279. X * state and where the next NFA is. */
  280. Xtypedef struct nfa_machine {
  281. X    DFAPTR        dfa;        /* The DFA for this eps transition */
  282. X    char        status;        /* DFA state */
  283. X    struct nfa_machine *next;     /* the next DFA in NFA */
  284. X} NFA, *NFAPTR;
  285. X
  286. X
  287. X
  288. X/* The next struct is used to link together DFA nodes for inference. */
  289. X
  290. Xtypedef struct dfal {
  291. X    struct tcell    *dl_meta;    /* link to %-meta cell        */
  292. X    struct dfal    *dl_next;    /* next cell on matched DFA list*/
  293. X    struct dfal    *dl_prev;    /* prev cell on matched DFA list*/
  294. X    struct dfal    *dl_member;    /* used during subset calc    */
  295. X    char        dl_delete;    /* used during subset calc    */
  296. X    char           *dl_per;    /* value of % for matched DFA   */
  297. X    statecnt        dl_state;    /* matched state of the DFA    */
  298. X    int        dl_prep;    /* repetion count for the cell    */
  299. X} DFALINK, *DFALINKPTR;
  300. X
  301. X
  302. X/* This struct is used to store the stack of DFA sets during inference */
  303. Xtypedef struct dfst {
  304. X   DFALINKPTR    df_set;            /* pointer to the set        */
  305. X   struct dfst *df_next;        /* next element in the stack    */
  306. X} DFASET, *DFASETPTR;
  307. X
  308. X
  309. X#endif
  310. SHAR_EOF
  311. chmod 0440 struct.h || echo "restore of struct.h fails"
  312. echo "x - extracting string.c (Text)"
  313. sed 's/^X//' << 'SHAR_EOF' > string.c &&
  314. X/* RCS      -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/string.c,v 1.1 90/10/06 12:04:14 dvadura Exp $
  315. X-- SYNOPSIS -- string handling code
  316. X-- 
  317. X-- DESCRIPTION
  318. X--    Routines to handle string manipulation.  This code is not specific
  319. X--    to dmake and has/and will be used in other programs.  The string
  320. X--    "" is considered the NULL string, if NIL(char) is received instead
  321. X--    undefined results may occurr.  (In reality NIL(char) is checked for
  322. X--    but in general it is not safe to assume NIL(char) ==  NULL)
  323. X-- 
  324. X-- AUTHOR
  325. X--      Dennis Vadura, dvadura@watdragon.uwaterloo.ca
  326. X--      CS DEPT, University of Waterloo, Waterloo, Ont., Canada
  327. X--
  328. X-- COPYRIGHT
  329. X--      Copyright (c) 1990 by Dennis Vadura.  All rights reserved.
  330. X-- 
  331. X--      This program is free software; you can redistribute it and/or
  332. X--      modify it under the terms of the GNU General Public License
  333. X--      (version 1), as published by the Free Software Foundation, and
  334. X--      found in the file 'LICENSE' included with this distribution.
  335. X-- 
  336. X--      This program is distributed in the hope that it will be useful,
  337. X--      but WITHOUT ANY WARRANTY; without even the implied warrant of
  338. X--      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  339. X--      GNU General Public License for more details.
  340. X-- 
  341. X--      You should have received a copy of the GNU General Public License
  342. X--      along with this program;  if not, write to the Free Software
  343. X--      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  344. X--
  345. X-- LOG
  346. X--     $Log:    string.c,v $
  347. X * Revision 1.1  90/10/06  12:04:14  dvadura
  348. X * dmake Release, Version 3.6
  349. X * 
  350. X*/
  351. X
  352. X#include "extern.h"
  353. X#include "alloc.h"
  354. X#include "db.h"
  355. X
  356. Xchar *
  357. X_strjoin( src, data, n, fr )/*
  358. X==============================
  359. X   Join data to src according to value of n.
  360. X
  361. X      n = -1   - return strcat( src, data )
  362. X      n >= 0   - return strncat( src, data, n )
  363. X
  364. X   FREE original src if fr == TRUE, else leave it alone */
  365. X
  366. Xchar *src;
  367. Xchar *data;
  368. Xint  n;
  369. Xint  fr;
  370. X{
  371. X   char *t;
  372. X   int  l;
  373. X   int  flag = FALSE;
  374. X
  375. X   DB_ENTER( "_strjoin" );
  376. X   
  377. X   if( src  == NIL( char ) ) { src = ""; flag = TRUE; }
  378. X   if( data == NIL( char ) ) data = "";
  379. X   DB_PRINT( "str", ("Joining [%s] [%s] %d", src, data, n) );
  380. X
  381. X   if( n == -1 )  n = strlen( data );
  382. X
  383. X   l = strlen( src ) + n + 1;
  384. X   if( (t = MALLOC( l, char )) == NIL( char ) ) No_ram();
  385. X
  386. X   strcpy( t, src );
  387. X   if (n) strncat( t, data, n );
  388. X   t[ l-1 ] = '\0';
  389. X
  390. X   if( !flag && fr ) FREE( src );
  391. X
  392. X   DB_PRINT( "str", ("Result  [%s]", t) );
  393. X   DB_RETURN( t );
  394. X}
  395. X
  396. X
  397. X
  398. X
  399. Xchar *
  400. X_stradd( src, data, fr )/*
  401. X==========================
  402. X   append data to src with space in between if src is not NIL( char ) or ""
  403. X   and free both src and data if fr == TRUE, otherwise leave them be */
  404. X
  405. Xchar *src;
  406. Xchar *data;
  407. Xint  fr;
  408. X{
  409. X   char *t;
  410. X   int  l;
  411. X   int  sflag;
  412. X   int  dflag;
  413. X
  414. X   DB_ENTER( "_stradd" );
  415. X
  416. X   sflag = dflag = fr;
  417. X
  418. X   if( src  == NIL( char ) ) { src  = ""; sflag = FALSE; }
  419. X   if( data == NIL( char ) ) { data = ""; dflag = FALSE; }
  420. X   DB_PRINT( "str", ("Adding [%s] [%s] %d", src, data, fr) );
  421. X
  422. X   l = strlen(src) + strlen(data) + 1;
  423. X   if( *src ) l++;
  424. X
  425. X   if( (t = MALLOC( l, char )) == NIL( char ) ) No_ram();
  426. X
  427. X   strcpy( t, src );
  428. X   
  429. X   if( *data )
  430. X   {
  431. X      if( *src ) strcat( t,  " " );
  432. X      strcat( t, data );
  433. X   }
  434. X
  435. X   if( sflag )  FREE( src  );
  436. X   if( dflag )  FREE( data );
  437. X
  438. X   DB_PRINT( "str", ("Result  [%s]", t) );
  439. X   DB_RETURN( t );
  440. X}
  441. X
  442. X
  443. X
  444. Xchar *
  445. X_strapp( src1, src2 )/*
  446. X=======================
  447. X   Append two strings together, and return the result with a space between
  448. X   the two strings.  FREE the first string if it is not NIL and always
  449. X   leave the second string be. */
  450. Xchar *src1;
  451. Xchar *src2;
  452. X{
  453. X   src2 = _stradd( src1, src2, FALSE );
  454. X   if( src1 != NIL( char ) ) FREE( src1 );
  455. X   return( src2 );
  456. X}
  457. X
  458. X
  459. X
  460. Xchar *
  461. X_strdup( str )/*
  462. X================  Duplicate the contents of a string, by using malloc */
  463. Xchar *str;
  464. X{
  465. X   char *t;
  466. X
  467. X   if( str == NIL( char ) ) return( NIL( char ) );
  468. X   
  469. X   if( (t = MALLOC( strlen( str )+1, char )) == NIL( char ) ) No_ram();
  470. X   strcpy( t, str );
  471. X
  472. X   return( t );
  473. X}
  474. X
  475. X
  476. X
  477. X
  478. Xchar *
  479. X_strpbrk( s1, s2 )/*
  480. X====================
  481. X   find first occurence of char in s2 in string s1.
  482. X   Returns a pointer to the first occurrence.  NOTE '\0' is considered part
  483. X   of s2 and a pointer to it is returned if no other chars match. */
  484. X
  485. Xchar *s1;
  486. Xchar *s2;
  487. X{
  488. X   register char *t;
  489. X
  490. X   if( s1 == NIL( char ) ) return( "" );
  491. X
  492. X   for( t=s1; *t && (strchr( s2, *t ) == NIL( char )); t++ );
  493. X   return( t );
  494. X}
  495. X
  496. X
  497. X
  498. X
  499. Xchar *
  500. X_strspn( s1, s2 )/*
  501. X===================
  502. X   return pointer to first char in s1 that does not belong to s2.
  503. X   Returns the pointer if match found, else returns pointer to null char
  504. X   in s1. (ie. "" ) */
  505. X   
  506. Xchar *s1;
  507. Xchar *s2;
  508. X{
  509. X   register char *t;
  510. X
  511. X   if( s1 == NIL( char ) ) return( "" );
  512. X
  513. X   for( t=s1; *t && (strchr( s2, *t ) != NIL( char )); t++ );
  514. X   return( t );
  515. X}
  516. X
  517. X
  518. X
  519. X
  520. Xchar *
  521. X_strstr( s1, s2 )/*
  522. X==================  find first occurrence in s1 of s2 */
  523. Xchar *s1;
  524. Xchar *s2;
  525. X{
  526. X   register char *s;
  527. X   register char *p;
  528. X   register char *r;
  529. X
  530. X   if( s1 != NIL(char) && s2 != NIL(char) )
  531. X      for( s=s1; *s; s++ )
  532. X     if( *s == *s2 )
  533. X     {
  534. X        for( r=s+1, p = s2+1; *p && (*r == *p); r++, p++ );
  535. X        if( !*p ) return( s );
  536. X     }
  537. X   
  538. X   return( NIL( char ) );
  539. X}
  540. X
  541. X
  542. X
  543. Xchar *
  544. X_substr( s, e )/*
  545. X=================
  546. X      Return the string between the two pointers s and e, not including the
  547. X      char that e points to.  NOTE:  This routine assumes that s and e point
  548. X      into the same string. */
  549. X
  550. Xchar *s;
  551. Xchar *e;
  552. X{
  553. X   char save;
  554. X
  555. X   save = *e;
  556. X   *e   = '\0';
  557. X   s    = _strdup( s );
  558. X   *e   = save;
  559. X
  560. X   return( s );
  561. X}
  562. SHAR_EOF
  563. chmod 0440 string.c || echo "restore of string.c fails"
  564. echo "x - extracting stat.c (Text)"
  565. sed 's/^X//' << 'SHAR_EOF' > stat.c &&
  566. X/* RCS      -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/stat.c,v 1.1 90/10/06 12:04:12 dvadura Exp $
  567. X-- SYNOPSIS -- bind a target name to a file.
  568. X-- 
  569. X-- DESCRIPTION
  570. X--    This file contains the code to go and stat a target.  The stat rules
  571. X--    follow a predefined order defined in the comment for Stat_target.
  572. X-- 
  573. X-- AUTHOR
  574. X--      Dennis Vadura, dvadura@watdragon.uwaterloo.ca
  575. X--      CS DEPT, University of Waterloo, Waterloo, Ont., Canada
  576. X--
  577. X-- COPYRIGHT
  578. X--      Copyright (c) 1990 by Dennis Vadura.  All rights reserved.
  579. X-- 
  580. X--      This program is free software; you can redistribute it and/or
  581. X--      modify it under the terms of the GNU General Public License
  582. X--      (version 1), as published by the Free Software Foundation, and
  583. X--      found in the file 'LICENSE' included with this distribution.
  584. X-- 
  585. X--      This program is distributed in the hope that it will be useful,
  586. X--      but WITHOUT ANY WARRANTY; without even the implied warrant of
  587. X--      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  588. X--      GNU General Public License for more details.
  589. X-- 
  590. X--      You should have received a copy of the GNU General Public License
  591. X--      along with this program;  if not, write to the Free Software
  592. X--      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  593. X--
  594. X-- LOG
  595. X--     $Log:    stat.c,v $
  596. X * Revision 1.1  90/10/06  12:04:12  dvadura
  597. X * dmake Release, Version 3.6
  598. X * 
  599. X*/
  600. X
  601. X#include "extern.h"
  602. X#include "alloc.h"
  603. X#include "db.h"
  604. X
  605. X
  606. Xstatic    int    _check_dir_list ANSI((CELLPTR, CELLPTR, int));
  607. X
  608. X#ifdef DBUG
  609. X   /* Just a little ditty for debugging this thing */
  610. X   static time_t
  611. X   _do_stat( name, lib, sym )
  612. X   char *name;
  613. X   char *lib;
  614. X   char **sym;
  615. X   {
  616. X      time_t res;
  617. X      DB_ENTER( "_do_stat" );
  618. X
  619. X      res = Do_stat(name, lib, sym);
  620. X      DB_PRINT( "stat", ("Statted [%s,%s,%d,%ld]", name, lib, sym, res) );
  621. X
  622. X      DB_RETURN( res );
  623. X   }   
  624. X#define DO_STAT(A,B,C)  _do_stat(A,B,C)
  625. X#else
  626. X#define DO_STAT(A,B,C)  Do_stat(A,B,C)
  627. X#endif
  628. X
  629. Xstatic char *_first;    /* local storage of first attempted path */
  630. X
  631. Xvoid
  632. XStat_target( cp, setfname )/*
  633. X=============================
  634. X    Stat a target.  When doing so follow the following rules, suppose
  635. X    that cp->CE_NAME points at a target called fred.o:
  636. X
  637. X        0.      If A_SYMBOL attribute set look into the library
  638. X            then do the steps 1 thru 4 on the resulting name.
  639. X        1.    Try path's obtained by prepending any dirs found as
  640. X            prerequisites for .SOURCE.o.
  641. X        2.    If not found, do same as 2 but use .SOURCE
  642. X        3.    If not found and .LIBRARYM attribute for the target is
  643. X            set then look for it in the corresponding library.
  644. X            4.    If found in step 0 thru 3, then ce_fname points at
  645. X            file name associate with target, else ce_fname points
  646. X            at a file name built by the first .SOURCE* dir that
  647. X            applied. */
  648. X
  649. XCELLPTR cp;
  650. Xint     setfname;
  651. X{
  652. X   register HASHPTR hp;
  653. X   static   HASHPTR srchp = NIL(HASH);
  654. X   char            *name;
  655. X   char            *tmp;
  656. X   int            res = 0;
  657. X
  658. X   DB_ENTER( "Stat_target" );
  659. X
  660. X   name = cp->CE_NAME;
  661. X   if( srchp == NIL(HASH) ) srchp = Get_name(".SOURCE",Defs,FALSE,NIL(CELL));
  662. X
  663. X   /* Look for a symbol of the form lib((symbol)) the name of the symbol
  664. X    * as entered in the hash table is (symbol) so pull out symbol and try
  665. X    * to find it's module.  If successful DO_STAT will return the module
  666. X    * as well as the archive member name (pointed at by tmp).  We then
  667. X    * replace the symbol name with the archive member name so that we
  668. X    * have the proper name for any future refrences. */
  669. X
  670. X   if( cp->ce_attr & A_SYMBOL ) {
  671. X      DB_PRINT( "stat", ("Binding lib symbol [%s]", name) );
  672. X      cp->ce_time = DO_STAT( name, cp->ce_lib, &tmp );
  673. X
  674. X      if( cp->ce_time != (time_t) 0L ) {
  675. X     /* stat the new member name below  note tmp must point at a string
  676. X      * returned by MALLOC... ie. the Do_stat code should use _strdup */
  677. X
  678. X     if( Verbose )
  679. X        printf( "%s:  Mapped ((%s)) to %s(%s)\n", Pname,
  680. X             name, cp->ce_lib, tmp );
  681. X
  682. X         FREE( name );        
  683. X     name = cp->CE_NAME = tmp;        
  684. X     cp->ce_attr &= ~(A_FFNAME | A_SYMBOL);
  685. X      }
  686. X      else
  687. X         { DB_VOID_RETURN; }
  688. X   }
  689. X
  690. X   _first = NIL(char);
  691. X   tmp = _strjoin( ".SOURCE", Get_suffix( name ), -1, FALSE);
  692. X
  693. X   /* Check .SOURCE.xxx target */
  694. X   if( (hp = Get_name(tmp, Defs, FALSE, NIL(CELL))) != NIL(HASH) )
  695. X      res = _check_dir_list( cp, hp->CP_OWNR, setfname );
  696. X
  697. X   /* Check just .SOURCE */
  698. X   if( !res && (srchp != NIL(HASH)) )
  699. X      res = _check_dir_list( cp, srchp->CP_OWNR, setfname );
  700. X
  701. X   /* If libmember and we haven't found it check the library */
  702. X   if( !res && (cp->ce_attr & A_LIBRARYM) )
  703. X       cp->ce_time = DO_STAT(name, cp->ce_lib, NIL(char *));
  704. X
  705. X   FREE( tmp );
  706. X
  707. X   if( (cp->ce_attr & A_FFNAME) && (cp->ce_fname != NIL(char)) )
  708. X      FREE( cp->ce_fname );
  709. X
  710. X   if( setfname )
  711. X      if( _first != NIL(char) ) {
  712. X     cp->ce_fname = _first;
  713. X     cp->ce_attr |= A_FFNAME;
  714. X      }
  715. X      else {
  716. X     cp->ce_fname = cp->CE_NAME;
  717. X     cp->ce_attr &= ~A_FFNAME;
  718. X      }
  719. X
  720. X   /* set it as stated only if successful, this way, we shall try again
  721. X    * later. */
  722. X   if( cp->ce_time != (time_t)0L ) cp->ce_flag |= F_STAT;
  723. X
  724. X   DB_VOID_RETURN;
  725. X}
  726. X
  727. X
  728. X
  729. Xstatic int
  730. X_check_dir_list( cp, sp, setfname )/*
  731. X=====================================
  732. X    Check the list of dir's given by the prerequisite list of sp, for a
  733. X    file pointed at by cp.  Returns 0 if path not bound, else returns
  734. X    1 and replaces old name for cell with new cell name. */
  735. X
  736. XCELLPTR cp;
  737. XCELLPTR sp;
  738. Xint     setfname;
  739. X{
  740. X   register LINKPTR lp;
  741. X   char *dir;
  742. X   char *path;
  743. X   char *name;
  744. X   int  res  = 0;
  745. X   int  fset = 0;
  746. X
  747. X   DB_ENTER( "_check_dir_list" );
  748. X   DB_PRINT( "mem", ("%s:-> mem %ld", cp->CE_NAME, (long) coreleft()) );
  749. X
  750. X   if( sp->CE_HOW != NIL(HOW) )        /* check prerequisites if any */
  751. X   {
  752. X      /* Use the real name instead of basename, this prevents silly
  753. X       * loops in inference code, and is consistent with man page */
  754. X      name = cp->CE_NAME;
  755. X
  756. X      /* Here we loop through each directory on the list, and try to stat
  757. X       * the target.  We always save the first pathname we try and stat in
  758. X       * _first.  If we subsequently get a match we then replace the value of
  759. X       * _first by the matched path name.  */
  760. X
  761. X      for( lp=sp->CE_PRQ; lp != NIL(LINK) && !res; lp=lp->cl_next ) {
  762. X     int  nodup = 0;
  763. X     dir  = lp->cl_prq->CE_NAME;
  764. X
  765. X     if( strchr( dir, '$' ) ) dir = Expand(dir);
  766. X     if( strcmp( dir, ".NULL" ) == 0 ) {
  767. X        nodup = 1;
  768. X        path = cp->CE_NAME;
  769. X     }
  770. X     else
  771. X        path = Build_path( dir, name );
  772. X
  773. X     res = ((cp->ce_time = DO_STAT(path,NIL(char),NIL(char *))) != (time_t)0L);
  774. X
  775. X     /* Have to use _strdup to set _first since Build_path, builds it's
  776. X      * path names inside a static buffer. */
  777. X     if( setfname )
  778. X        if( (_first == NIL(char) && !fset) || res ) {
  779. X           if( _first != NIL(char) ) FREE( _first );
  780. X           _first = nodup ? NIL(char) : _strdup(path);
  781. X           fset = 1;
  782. X        }
  783. X
  784. X     DB_PRINT( "stat", ("_first [%s], path [%s]", _first, path) );
  785. X     if( dir != lp->cl_prq->CE_NAME )  FREE(dir);
  786. X      }
  787. X   }
  788. X
  789. X   DB_PRINT( "mem", ("%s:-< mem %ld", cp->CE_NAME, (long) coreleft()) );
  790. X   DB_RETURN( res );
  791. X}
  792. SHAR_EOF
  793. chmod 0440 stat.c || echo "restore of stat.c fails"
  794. echo "x - extracting rulparse.c (Text)"
  795. sed 's/^X//' << 'SHAR_EOF' > rulparse.c &&
  796. X/* RCS      -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/rulparse.c,v 1.1 90/10/06 12:04:10 dvadura Exp $
  797. X-- SYNOPSIS -- perform semantic analysis on input
  798. X-- 
  799. X-- DESCRIPTION
  800. X--    This code performs semantic analysis on the input, and builds
  801. X--    the complex internal datastructure that is used to represent
  802. X--    the user makefile.
  803. X-- 
  804. X-- AUTHOR
  805. X--      Dennis Vadura, dvadura@watdragon.uwaterloo.ca
  806. X--      CS DEPT, University of Waterloo, Waterloo, Ont., Canada
  807. X--
  808. X-- COPYRIGHT
  809. X--      Copyright (c) 1990 by Dennis Vadura.  All rights reserved.
  810. X-- 
  811. X--      This program is free software; you can redistribute it and/or
  812. X--      modify it under the terms of the GNU General Public License
  813. X--      (version 1), as published by the Free Software Foundation, and
  814. X--      found in the file 'LICENSE' included with this distribution.
  815. X-- 
  816. X--      This program is distributed in the hope that it will be useful,
  817. X--      but WITHOUT ANY WARRANTY; without even the implied warrant of
  818. X--      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  819. X--      GNU General Public License for more details.
  820. X-- 
  821. X--      You should have received a copy of the GNU General Public License
  822. X--      along with this program;  if not, write to the Free Software
  823. X--      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  824. X--
  825. X-- LOG
  826. X--     $Log:    rulparse.c,v $
  827. X * Revision 1.1  90/10/06  12:04:10  dvadura
  828. X * dmake Release, Version 3.6
  829. X * 
  830. X*/
  831. X
  832. X#include <ctype.h>
  833. X#include "extern.h"
  834. X#include "alloc.h"
  835. X#include "db.h"
  836. X
  837. X/* prototypes for local functions */
  838. Xstatic  void    _add_global_prereq ANSI((CELLPTR));
  839. Xstatic    void    _build_graph ANSI((int, CELLPTR, CELLPTR));
  840. Xstatic    char*    _build_meta ANSI((char*));
  841. Xstatic    int    _do_magic ANSI((int, char*, CELLPTR, CELLPTR, t_attr, char*));
  842. Xstatic    void    _do_special ANSI((int, int, t_attr,char*,CELLPTR,CELLPTR,int*));
  843. Xstatic    int    _do_targets ANSI((int, t_attr, char*, CELLPTR, CELLPTR));
  844. Xstatic    t_attr    _is_attribute ANSI((char*));
  845. Xstatic    int    _is_special ANSI((char*));
  846. Xstatic    char*    _is_magic ANSI((char*));
  847. Xstatic    int    _is_percent ANSI((char*));
  848. Xstatic    void    _set_attributes ANSI((t_attr, char*, CELLPTR));
  849. Xstatic    void    _stick_at_head ANSI((HOWPTR, CELLPTR));
  850. Xstatic    void    _set_global_attr ANSI((t_attr, char*));
  851. X
  852. X/* static variables that must persist across invocation of Parse_rule_def */
  853. Xstatic CELLPTR    _sv_targets = NIL(CELL);
  854. Xstatic STRINGPTR  _sv_rules   = NIL(STRING);
  855. Xstatic STRINGPTR  _sv_crule   = NIL(STRING);
  856. Xstatic EDGEPTR    _sv_edgel   = NIL(EDGE);
  857. Xstatic LINKPTR    _sv_glb_prq = NIL(LINK);
  858. Xstatic int      _sp_target  = FALSE;
  859. Xstatic t_attr     _sv_attr;
  860. Xstatic t_attr     _sv_attro;
  861. Xstatic int        _sv_flag;
  862. Xstatic int      _sv_op;
  863. Xstatic char      *_sv_setdir;
  864. Xstatic char      _sv_globprq_only = 0;
  865. X
  866. X/* Define for common attribute mask */
  867. X#define A_HOW    (A_IGNORE | A_SILENT | A_SHELL | A_SWAP)
  868. X#define A_GLOB     (A_PRECIOUS | A_SILENT | A_IGNORE | A_EPILOG |\
  869. X          A_PROLOG | A_NOINFER | A_SEQ | A_SHELL | A_SWAP | A_MKSARGS)
  870. X
  871. X
  872. X
  873. Xint
  874. XParse_rule_def( state )/*
  875. X=========================
  876. X   Parse the rule definition contained in Buffer, and modify the state 
  877. X   if appropriate.  The function returns 0, if the definition is found to
  878. X   be an illegal rule definition, and it returns 1 if it is a rule definition.
  879. X   */
  880. Xint *state;
  881. X{
  882. X   TKSTR     input;        /* input string struct for token search      */
  883. X   CELLPTR    targets;    /* list of targets if any          */
  884. X   CELLPTR    prereq;        /* list of prereq if any          */
  885. X   CELLPTR    prereqtail;    /* tail of prerequisite list          */
  886. X   CELLPTR    cp;        /* temporary cell pointer for list making */
  887. X   char     *result;    /* temporary storage for result            */
  888. X   char        *tok;        /* temporary pointer for tokens          */
  889. X   char         *set_dir;       /* value of setdir attribute              */
  890. X   char        *brk;        /* break char list for Get_token      */
  891. X   char         *firstrcp;      /* first recipe line, from ; in rule line */
  892. X   t_attr       attr;           /* sum of attribute flags for current tgts*/
  893. X   t_attr    at;        /* temp place to keep an attribute code      */
  894. X   int        op;        /* rule operator              */
  895. X   int        special;    /* indicate special targets in rule      */
  896. X   int        percent;    /* indicate percent rule target          */
  897. X   int        mixed_glob_prq; /* indicate mixed %-rule prereq possible  */
  898. X
  899. X   DB_ENTER( "Parse_rule_def" );
  900. X
  901. X   op          = 0;
  902. X   attr       = 0;
  903. X   special    = 0;
  904. X   percent    = 0;
  905. X   set_dir    = NIL( char );
  906. X   targets    = NIL(CELL);
  907. X   prereq     = NIL(CELL);
  908. X   prereqtail = NIL(CELL);
  909. X   mixed_glob_prq = 0;
  910. X
  911. X   /* Check to see if the line is of the form:
  912. X    *    targets : prerequisites; first recipe line
  913. X    * If so remember the first_recipe part of the line. */
  914. X
  915. X   firstrcp = strchr( Buffer, ';' );
  916. X   if( firstrcp != NIL( char ) ) {
  917. X      *firstrcp++ = 0;
  918. X      firstrcp = _strspn( firstrcp, " \t" );
  919. X   }
  920. X
  921. X   result = Expand( Buffer );
  922. X   for( brk=strchr(result,'\\'); brk != NIL(char); brk=strchr(brk,'\\') )
  923. X      if( brk[1] == '\n' )
  924. X     *brk = ' ';
  925. X      else
  926. X         brk++;
  927. X
  928. X   DB_PRINT( "par", ("Scanning: [%s]", result) );
  929. X
  930. X   SET_TOKEN( &input, result );
  931. X   brk = ":-^!";
  932. X   Def_targets = TRUE;
  933. X   
  934. X   /* Scan the input rule line collecting targets, the operator, and any
  935. X    * prerequisites.  Stop when we run out of targets and prerequisites. */
  936. X
  937. X   while( *(tok = Get_token( &input, brk, TRUE )) != '\0' )
  938. X      if( !op ) {
  939. X     /* we are scanning targets and attributes
  940. X      * check to see if token is an operator.  */
  941. X
  942. X     op = Rule_op( tok );
  943. X
  944. X     if( !op ) {
  945. X        /* define a new cell, or get old cell  */
  946. X        cp = Def_cell(tok, NIL(CELL));
  947. X        DB_PRINT( "par", ("tg_cell [%s]", tok) );
  948. X        
  949. X        if( at = _is_attribute( tok ) ) {
  950. X           /* Logically OR the attributes specified into one main
  951. X            * ATTRIBUTE mask. */
  952. X
  953. X           if( at == A_SETDIR )
  954. X              if( set_dir != NIL( char ) )
  955. X                 Fatal( "Only one .SETDIR attribute allowed in rule line" );
  956. X              else
  957. X                 set_dir = _strdup( tok );
  958. X
  959. X           attr |= at;
  960. X        }
  961. X        else {
  962. X           int tmp;
  963. X           
  964. X           tmp = _is_special( tok );
  965. X           if( _is_percent( tok ) ) percent++;
  966. X
  967. X           if( percent )
  968. X              if( targets != NIL(CELL) )
  969. X             Fatal( "Multiple targets are not allowed in %% rules" );
  970. X          else
  971. X             cp->ce_flag |= F_PERCENT;
  972. X
  973. X           if( special )
  974. X              Fatal( "Special target must appear alone", tok );
  975. X           else if( !(cp->ce_flag & F_MARK) ) {
  976. X          cp->ce_link  = targets;  /* targets are stacked in this list*/
  977. X          cp->ce_flag |= F_MARK | F_EXPLICIT;
  978. X          targets      = cp;
  979. X
  980. X          special = tmp;
  981. X           }
  982. X           else if( !(cp->ce_attr & A_LIBRARY) )
  983. X          Warning("Duplicate entry [%s] in target list",cp->CE_NAME);
  984. X        }
  985. X     }
  986. X     else {
  987. X        /* found an operator so empty out break list
  988. X         * and clear mark bits on target list, setting them all to F_USED */
  989. X
  990. X        brk  = "";
  991. X        for( cp=targets; cp != NIL(CELL); cp=cp->ce_link ) {
  992. X           cp->ce_flag ^= F_MARK;
  993. X           cp->ce_flag |= F_USED;
  994. X        }
  995. X
  996. X        Def_targets = FALSE;
  997. X     }
  998. X      }
  999. X      else {
  1000. X         /* Scanning prerequisites so build the prerequisite list.  We use
  1001. X          * F_MARK flag to make certain we have only a single copy of the
  1002. X          * prerequisite in the list */
  1003. X
  1004. X     cp = Def_cell( tok, NIL(CELL) );
  1005. X
  1006. X     if( _is_percent( tok ) ) {
  1007. X        if( !percent && !attr )
  1008. X           Fatal( "Syntax error in %% rule, missing %% target");
  1009. X        mixed_glob_prq = 1;
  1010. X     }
  1011. X
  1012. X     if( cp->ce_flag & F_USED ) {
  1013. X        if( cp->ce_attr & A_COMPOSITE )
  1014. X           continue;
  1015. X        else
  1016. X           Fatal( "Detected circular dependency in graph at [%s]",
  1017. X              cp->CE_NAME );
  1018. X     }
  1019. X         else if( !(cp->ce_flag & F_MARK) ) {
  1020. X        DB_PRINT( "par", ("pq_cell [%s]", tok) );
  1021. X        cp->ce_flag |= F_MARK;
  1022. X
  1023. X        if( prereqtail == NIL(CELL) )    /* keep prereq's in order */
  1024. X           prereq = cp;
  1025. X        else
  1026. X           prereqtail->ce_link = cp;
  1027. X
  1028. X        prereqtail = cp;
  1029. X     }
  1030. X     else if( !(cp->ce_attr & A_LIBRARY) )
  1031. X        Warning("Duplicate entry [%s] in prerequisite list",cp->CE_NAME);
  1032. X      }
  1033. X      
  1034. X   /* Check to see if we have a percent rule that has only global
  1035. X    * prerequisites.  If so then set the flag so that later on, we don't issue
  1036. X    * an error if such targets supply an empty set of rules. */
  1037. X
  1038. X   if( percent && !mixed_glob_prq && (prereq != NIL(CELL)) )
  1039. X      _sv_globprq_only = 1;
  1040. X
  1041. X   /* It's ok to have targets with attributes, and no prerequisites, but it's
  1042. X    * not ok to have no targets and no attributes, or no operator */
  1043. X
  1044. X   if( !op ) {
  1045. X      CLEAR_TOKEN( &input );
  1046. X      DB_PRINT( "par", ("Not a rule [%s]", Buffer) );
  1047. X      DB_RETURN( 0 );
  1048. X   }
  1049. X
  1050. X   if( !attr && targets == NIL(CELL) ) {
  1051. X      Fatal( "Missing targets or attributes in rule" );
  1052. X      if( set_dir != NIL( char )) FREE( set_dir );
  1053. X      DB_RETURN( 0 );
  1054. X   }
  1055. X
  1056. X   /* We have established we have a legal rules line, so we must process it.
  1057. X    * In doing so we must handle any special targets.  Special targets must
  1058. X    * appear alone possibly accompanied by attributes.
  1059. X    * NOTE:  special != 0  ==> targets != NIL(CELL) */
  1060. X    
  1061. X   if( prereqtail != NIL(CELL) ) prereqtail->ce_link = NIL(CELL);
  1062. X
  1063. X   /* Clear out MARK bits used in duplicate checking.  I originally wanted
  1064. X    * to do this as the lists get processed but that got too error prone
  1065. X    * so I bit the bullit and added these two loops. */
  1066. X
  1067. X   for( cp=prereq;  cp != NIL(CELL); cp=cp->ce_link ) cp->ce_flag &= ~F_MARK;
  1068. X   for( cp=targets; cp != NIL(CELL); cp=cp->ce_link ) cp->ce_flag &= ~F_USED;
  1069. X
  1070. X   /* Check to see if the previous rule line was bound if, not the call
  1071. X    * Bind_rules_to_targets to go and bind the line */
  1072. X
  1073. X   if( _sv_rules != NIL(STRING) ) Bind_rules_to_targets( F_DEFAULT );
  1074. X
  1075. X   /* Add the first recipe line to the list */
  1076. X   if( firstrcp != NIL( char ) )
  1077. X      Add_recipe_to_list( firstrcp, TRUE, FALSE );
  1078. X
  1079. X   if( special )
  1080. X      _do_special( special, op, attr, set_dir, targets, prereq, state );
  1081. X   else
  1082. X      *state = _do_targets( op, attr, set_dir, targets, prereq );
  1083. X
  1084. X   _sv_op     = op;
  1085. X   _sv_setdir = set_dir;
  1086. X   DB_RETURN( 1 );
  1087. X}
  1088. X
  1089. X
  1090. X
  1091. X
  1092. Xint
  1093. XRule_op( op )/*
  1094. X================
  1095. X   Check the passed in op string and map it to one of the rule operators */
  1096. Xchar *op;
  1097. X{
  1098. X   int ret = 0;
  1099. X
  1100. X   DB_ENTER( "rule_op" );
  1101. X   
  1102. X   if( *op == TGT_DEP_SEP ) {
  1103. X      ret = R_OP_CL;
  1104. X      op++;
  1105. X
  1106. X      /* All rule operations begin with a :, but may include any one of the
  1107. X       * four modifiers.  In order for the rule to be properly mapped we must
  1108. X       * check for each of the modifiers in turn, building up our return bit
  1109. X       * string. */
  1110. X
  1111. X      while( *op && ret )
  1112. X         switch( *op ) {
  1113. X        case ':': ret |= R_OP_DCL; op++; break;
  1114. X        case '!': ret |= R_OP_BG;  op++; break;
  1115. X        case '^': ret |= R_OP_UP;  op++; break;
  1116. X        case '-': ret |= R_OP_MI;  op++; break;
  1117. X
  1118. X        default : ret  = 0;  /* an invalid modifier, chuck whole string */
  1119. X         }
  1120. X
  1121. X      if( *op != '\0' ) ret = 0;
  1122. X   }
  1123. X
  1124. X   DB_RETURN( ret );
  1125. X}
  1126. X
  1127. X
  1128. X
  1129. X
  1130. Xvoid
  1131. XAdd_recipe_to_list( rule, white_too, no_check )/*
  1132. X=================================================
  1133. X        Take the provided string and add it to the list of recipe lines
  1134. X    we are saving to be added to the list of targets we have built
  1135. X    previously.  If white_too == TRUE add the rule EVEN IF it contains only
  1136. X        whitespace. */
  1137. Xchar *rule;
  1138. Xint  white_too;
  1139. Xint  no_check;
  1140. X{
  1141. X   DB_ENTER( "Add_recipe_to_list" );
  1142. X
  1143. X   if( rule != NIL( char ) && (*rule != '\0' || white_too) ) {
  1144. X      DB_PRINT( "par", ("Adding recipe [%s]", rule) );
  1145. X      _sv_crule = Def_recipe( rule, _sv_crule, white_too, no_check );
  1146. X
  1147. X      if( _sv_rules == NIL(STRING) )
  1148. X         _sv_rules = _sv_crule;
  1149. X   }
  1150. X
  1151. X   DB_VOID_RETURN;
  1152. X}
  1153. X
  1154. X
  1155. X
  1156. Xvoid
  1157. XBind_rules_to_targets( flag )/*
  1158. X===============================
  1159. X        Take the rules we have defined and bind them with proper attributes
  1160. X        to the targets that were previously defined in the parse.  The
  1161. X        attributes that get passed here are merged with those that are were
  1162. X        previously defined.  (namely F_SINGLE) */
  1163. Xint flag;
  1164. X{
  1165. X   CELLPTR tg;             /* pointer to current target in list */
  1166. X   LINKPTR lp;           /* pointer to link cell        */
  1167. X   HOWPTR  how;           /* pointer to targets main HOW cell    */
  1168. X   int     magic;          /* TRUE if target is .xxx.yyy form   */
  1169. X   int     tflag;          /* TRUE if we assigned targets here  */
  1170. X
  1171. X   DB_ENTER( "Bind_rules_to_targets" );
  1172. X
  1173. X   /* This line is needed since Parse may call us twice when the last
  1174. X    * GROUP rule appears at the end of file.  In this case the rules
  1175. X    * have already been bound and we want to ignore them. */
  1176. X
  1177. X   if( _sv_targets == NIL(CELL) ) { DB_VOID_RETURN; }
  1178. X
  1179. X   tflag  = FALSE;
  1180. X   flag  |= (_sv_flag & F_SINGLE);
  1181. X
  1182. X   for( tg = _sv_targets; tg != NIL(CELL); tg = tg->ce_link ) {
  1183. X      DB_PRINT( "par", ("Binding to %s, %04x", tg->CE_NAME, tg->ce_flag) );
  1184. X      magic = tg->ce_flag & F_PERCENT;
  1185. X
  1186. X      /* Check to see if we had a rule of the form '%.o : a.h b.h ; xxx'
  1187. X       * In which case we must build a NULL prq node to hold the recipe */
  1188. X
  1189. X      if( _sv_globprq_only && (_sv_rules != NIL(STRING)) )
  1190. X     _build_graph( _sv_op, tg, NIL(CELL) );
  1191. X
  1192. X      /* NOTE:  For targets that are magic we ignore any previously defined
  1193. X       *        rules.  ie. We throw away the old definition and use the new. */
  1194. X
  1195. X      if( !(tg->ce_flag & F_MULTI) && !magic && (tg->CE_RECIPE != NIL(STRING))
  1196. X      && !_sp_target && (_sv_rules != NIL(STRING)) )
  1197. X         Fatal( "Multiply defined recipe for target %s", tg->CE_NAME );
  1198. X
  1199. X      if( (magic || _sp_target) && (_sv_rules == NIL(STRING)) &&
  1200. X      !(tg->ce_flag & F_SPECIAL) && !_sv_globprq_only )
  1201. X         Warning( "Empty recipe for special target %s", tg->CE_NAME );
  1202. X
  1203. X      if( magic ) {
  1204. X     EDGEPTR el;
  1205. X
  1206. X     for( el=_sv_edgel; el != NIL(EDGE); el=el->ed_link ) {
  1207. X        how = el->ed_how;
  1208. X        how->hw_flag |= flag;
  1209. X
  1210. X        _set_attributes( _sv_attro, _sv_setdir, el->ed_tg );
  1211. X
  1212. X        if( _sv_rules != NIL(STRING) ) {
  1213. X           how->hw_recipe  = _sv_rules;
  1214. X           how->hw_attr   |= _sv_attr & A_HOW;
  1215. X           how->hw_indprq = _sv_glb_prq;
  1216. X        }
  1217. X     }
  1218. X      }
  1219. X      else {
  1220. X     how = tg->CE_HOW;
  1221. X     how->hw_flag |= flag;
  1222. X
  1223. X     if( _sv_rules != NIL(STRING) ) {
  1224. X        how->hw_recipe  = _sv_rules;
  1225. X        how->hw_attr   |= _sv_attr & A_HOW;
  1226. X        tg->ce_flag    |= F_RULES | F_TARGET;
  1227. X
  1228. X        /* Bind the current set of prerequisites as belonging to the
  1229. X         * original recipe given for the target */
  1230. X
  1231. X        for( lp=how->hw_prq; lp != NIL(LINK); lp = lp->cl_next )
  1232. X          if( !(lp->cl_flag & F_USED) ) lp->cl_flag |= F_TARGET;
  1233. X         }
  1234. X     else
  1235. X        for( lp=how->hw_prq; lp != NIL(LINK); lp = lp->cl_next )
  1236. X          lp->cl_flag |= F_USED;
  1237. X      }
  1238. X
  1239. X      if( !Target && !magic && !(tg->ce_flag & F_SPECIAL) ) {
  1240. X     Add_fringe( tg );
  1241. X
  1242. X     tg->ce_flag |= F_TARGET;
  1243. X     tflag        = TRUE;
  1244. X      }
  1245. X
  1246. X      /* Break since all prerequisites are attached and all targets in the
  1247. X       * .UPDATEALL list point at the same HOW cell. */
  1248. X      if( tg->ce_all != NIL(CELL) ) {
  1249. X     CELLPTR tcp = tg;
  1250. X
  1251. X     /* Make sure all people participating in a .UPDATEALL prerequisite
  1252. SHAR_EOF
  1253. echo "End of part 5"
  1254. echo "File rulparse.c is continued in part 6"
  1255. echo "6" > s2_seq_.tmp
  1256. exit 0
  1257.  
  1258.